package org.maxgroundstation.groundstation.view.overlay;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Arc2D;
import java.text.DecimalFormat;

import org.maxgroundstation.groundstation.GroundStation;
import org.maxgroundstation.groundstation.comm.service.wifi.WiFiService;

/**
 * An overlay for displaying WiFi signal strength.
 * @author Scott Davis
 * 
 * Copyright (C) 2010  Scott Davis
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class WiFiSignalStrengthOverlay implements Overlay {

    // Static members.
    private static final Color BG_COLOR = new Color(0, 0, 0, 127);
    private static final Stroke FG_STROKE = new BasicStroke(4F, BasicStroke.CAP_ROUND, 
            BasicStroke.JOIN_MITER);
    private static final Stroke BG_STROKE = new BasicStroke(6F, BasicStroke.CAP_ROUND, 
            BasicStroke.JOIN_MITER);
    
    // Data members.
    private GroundStation gs;
    private boolean display;
    private DecimalFormat formatter;
    
    public WiFiSignalStrengthOverlay(GroundStation gs) {
        // Initialize data members.
        this.gs = gs;
        display = true;
        formatter = new DecimalFormat("0");
    }
    
    @Override
    public boolean canDisplay() {
        return gs.getServiceComm().hasService(WiFiService.SERVICE_ID);
    }

    @Override
    public boolean getDisplay() {
        return display;
    }

    @Override
    public String getName() {
        return "WiFi Signal Strength";
    }
    
    /**
     * Gets the WiFi signal strength service .
     * @return WiFi signal strength service or null if none.
     */
    private WiFiService getWiFiService() {
        return (WiFiService) gs.getServiceComm().getService(WiFiService.SERVICE_ID);
    }

    @Override
    public void paintOverlay(Graphics g, int panelWidth, int panelHeight) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.GREEN);
        Stroke saveStroke = g2d.getStroke();
        
        int centerX = panelWidth - 100;
        int bottomY = panelHeight - 50;
        
        WiFiService wifiService = getWiFiService();
        if (wifiService != null) {
            // Draw WiFi string.
            g2d.setFont(new Font(g2d.getFont().getFontName(), Font.BOLD, 10));
            String wifiString = "WiFi";
            TextDisplayUtil.drawText(wifiString, centerX, bottomY + 10, g);
            
            // Draw signal strength string.
            float signalStrength = wifiService.getWiFiSignalStrength();
            String signalStrengthString = formatter.format(signalStrength) + "%";
            TextDisplayUtil.drawText(signalStrengthString, centerX, bottomY + 25, g);
            
            // Set drawing stroke.
            g2d.setStroke(new BasicStroke(4F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
            
            // Draw the dark arcs.
            Color darkBarColor = new Color(0F, .10F, 0F);     
            for (int x = 0; x < 100; x += 20) {
                float arcX = centerX - (x / 4F) + 1F;
                float arcY = bottomY - 11F - (x / 2F);
                float arcWidth = (x / 2F) + 1F;
                float arcHeight = (x / 2F) + 1F;
                drawShape(g2d, new Arc2D.Float(arcX, arcY, arcWidth, arcHeight, 40F, 100F, 
                        Arc2D.OPEN), darkBarColor, BG_COLOR);
            }
            
            // Draw the light arcs.
            for (int x = 0; x < 100; x += 20) {
                float opacity = 1F;
                float arcStrength = 75F + (x / 4F);
                if (signalStrength < (arcStrength + 5F)) {
                    opacity = (signalStrength - arcStrength) / 5F;
                    if (opacity < 0F) opacity = 0F;
                }
                
                Color litBarColor = new Color(0F, 1F, 0F, opacity);
                
                float arcX = centerX - (x / 4F) + 1F;
                float arcY = bottomY - 11F - (x / 2F);
                float arcWidth = (x / 2F) + 1F;
                float arcHeight = (x / 2F) + 1F;
                drawShape(g2d, new Arc2D.Float(arcX, arcY, arcWidth, arcHeight, 40F, 100F, 
                        Arc2D.OPEN), litBarColor, BG_COLOR);
            }
        }
        
        // Reset original stroke.
        g2d.setStroke(saveStroke);
    }
    
    /**
     * Draw a shape with a background outline.
     * @param g2d the graphics context.
     * @param shape the shape to draw.
     * @param fgColor the foreground color.
     * @param bgColor the background color.
     */
    private void drawShape(Graphics2D g2d, Shape shape, Color fgColor, Color bgColor) {
        g2d.setStroke(BG_STROKE);
        g2d.setColor(bgColor);
        g2d.draw(shape);
        g2d.setStroke(FG_STROKE);
        g2d.setColor(fgColor);
        g2d.draw(shape);
    }

    @Override
    public void setDisplay(boolean displayOverlay) {
        this.display = displayOverlay;
    }
}